﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Net;
using System.IO;
using Newtonsoft.Json;

using Res = WasaWasa.Properties.Resources;
using System.Threading;

namespace WasaWasa
{
    partial class MainWindow
    {
        private const string ApiPathCreateFollow = "/friendships/create/{0}.json";
        private const string ApiPathDestroyFollow = "/friendships/destroy/{0}.json";

        private ObservableCollection<UserListBundle> userLists;

        partial void InitializeUserListTab()
        {
            userLists = new ObservableCollection<UserListBundle>();
            userLists.Add(new UserListBundle() { Type = UserListType.Friends, Name = Res.StringFriends, ApiPath = "/statuses/friends.json" });
            userLists.Add(new UserListBundle() { Type = UserListType.Followers, Name = Res.StringFollowers, ApiPath = "/statuses/followers.json" });
            userLists.Add(new UserListBundle() { Type = UserListType.Footprints, Name = Res.StringFootprints, ApiPath = "/footmark/recent.json" });
            Resources["userLists"] = userLists;
            tabsUserlist.SelectedIndex = 0;
        }

        /// <summary>
        /// ユーザーリストを取得して表示します。
        /// </summary>
        /// <param name="idx">ユーザーリストのインデックス</param>
        private void LoadUserList(UserListBundle ulb)
        {
            AppendLogText(ulb.Name + Res.MessageLoadingUserList);
            ulb.IsLoaded = true;

            UriBuilder ub = new UriBuilder(Uri.UriSchemeHttp, ApiHost, ApiPort, ulb.ApiPath);

            HttpWebRequest wreq = WebRequest.Create(ub.Uri) as HttpWebRequest;
            wreq.Method = WebRequestMethods.Http.Get;
            if (!SetWebRequestOptions(wreq)) return;
            IAsyncResult oar = wreq.BeginGetResponse(new AsyncCallback(delegate(IAsyncResult ar)
            {
                try
                {
                    using (HttpWebResponse wres = wreq.EndGetResponse(ar) as HttpWebResponse)
                    {
                        AppendLogText(ulb.Name + Res.OperationLoadUserList + Enum.GetName(typeof(HttpStatusCode), wres.StatusCode));

                        if (wres.StatusCode == HttpStatusCode.OK)
                        {
                            using (Stream sres = wres.GetResponseStream())
                            using (StreamReader srres = new StreamReader(sres))
                            using (JsonTextReader jtr = new JsonTextReader(srres))
                            {
                                List<UserClass> tul = null;
                                try
                                {
                                    tul = new JsonSerializer().Deserialize(jtr, typeof(List<UserClass>)) as List<UserClass>;
                                }
                                catch (JsonReaderException)
                                {
                                    AppendLogText(ulb.Name + Res.OfUserList + Res.ErrorFailedReadingJson);
                                    return;
                                }
                                catch (JsonSerializationException ex)
                                {
                                    AppendLogText(ulb.Name + Res.OfUserList + Res.ErrorFailedSerializingJson);
                                    Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
                                    {
                                        ExceptionWindow.Show(ex);
                                    }));
                                }
                                ObservableCollection<UserClass> gul = ulb.Users;

                                Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                                {
                                    gul.Clear();
                                    foreach (var ul in tul)
                                    {
                                        gul.Add(ul);
                                    }
                                    ulb.LastLoadedCount = gul.Count;
                                }));
                                ulb.LastLoaded = DateTime.Now;
                            }
                        }
                    }
                }
                catch (WebException ex)
                {
                    AppendLogText(ulb.Name + Res.OperationLoadUserList + Enum.GetName(typeof(HttpStatusCode), (ex.Response as HttpWebResponse).StatusCode));
                }
            }), null);
            ThreadPool.RegisterWaitForSingleObject(oar.AsyncWaitHandle, new WaitOrTimerCallback(TimeOutCallback), new object[] { wreq, ulb.Name + Res.OperationLoadUserList }, 30000, true);
        }

        /// <summary>
        /// 指定されたユーザを購読します。
        /// </summary>
        /// <param name="loginId">購読するユーザのログインID</param>
        private void CreateFollow(string loginId)
        {
            AppendLogText(loginId + Res.To + Res.MessageCreatingFollow);

            UriBuilder ub = new UriBuilder(Uri.UriSchemeHttp, ApiHost, ApiPort,
                string.Format(ApiPathCreateFollow, loginId));

            HttpWebRequest wreq = WebRequest.Create(ub.Uri) as HttpWebRequest;
            wreq.Method = WebRequestMethods.Http.Post;
            if (!SetWebRequestOptions(wreq)) return;
            IAsyncResult oar = wreq.BeginGetResponse(new AsyncCallback(delegate(IAsyncResult ar)
            {
                try
                {
                    using (HttpWebResponse wres = wreq.EndGetResponse(ar) as HttpWebResponse)
                    {
                        AppendLogText(loginId + Res.To + Res.OperationCreateFollow + Enum.GetName(typeof(HttpStatusCode), wres.StatusCode));
                    }
                }
                catch (WebException ex)
                {
                    AppendLogText(loginId + Res.To + Res.OperationCreateFollow + Enum.GetName(typeof(HttpStatusCode), (ex.Response as HttpWebResponse).StatusCode));
                }
            }), null);
            ThreadPool.RegisterWaitForSingleObject(oar.AsyncWaitHandle, new WaitOrTimerCallback(TimeOutCallback), new object[] { wreq, loginId + Res.To + Res.OperationCreateFollow }, 30000, true);
        }

        /// <summary>
        /// 指定されたユーザを購読解除します。
        /// </summary>
        /// <param name="loginId">購読解除するユーザのログインID</param>
        private void DestoryFollow(string loginId)
        {
            AppendLogText(loginId + Res.To + Res.MessageDestroyingFollow);

            UriBuilder ub = new UriBuilder(Uri.UriSchemeHttp, ApiHost, ApiPort,
                string.Format(ApiPathDestroyFollow, loginId));

            HttpWebRequest wreq = WebRequest.Create(ub.Uri) as HttpWebRequest;
            wreq.Method = WebRequestMethods.Http.Post;
            if (!SetWebRequestOptions(wreq)) return;
            IAsyncResult oar = wreq.BeginGetResponse(new AsyncCallback(delegate(IAsyncResult ar)
            {
                try
                {
                    using (HttpWebResponse wres = wreq.EndGetResponse(ar) as HttpWebResponse)
                    {
                        AppendLogText(loginId + Res.To + Res.OperationDestroyFollow + Enum.GetName(typeof(HttpStatusCode), wres.StatusCode));
                    }
                }
                catch (WebException ex)
                {
                    AppendLogText(loginId + Res.To + Res.OperationDestroyFollow + Enum.GetName(typeof(HttpStatusCode), (ex.Response as HttpWebResponse).StatusCode));
                }
            }), null);
            ThreadPool.RegisterWaitForSingleObject(oar.AsyncWaitHandle, new WaitOrTimerCallback(TimeOutCallback), new object[] { wreq, loginId + Res.To + Res.OperationDestroyFollow }, 30000, true);
        }
    }
}
